/*************************************************************************
    > File Name:    config_setting.h
	> Author:       陈猛
	> Mail:         chen-meng@example.com
	> Created Time: 2019年09月12日 星期四 16时07分18秒
    > Description:  系统配置文件读取分析，管理系统一些只读的配置文件
                    如果配置文件需要被程序修改的代码部分不放在此处
 ************************************************************************/

/**********************************
 * 只读配置文件的格式
 * [system]
 * # GAL engine
 * gal_engine=fbcon
 ********************************/
#ifndef _CONFIG_SETTING_H_
#define _CONFIG_SETTING_H_

#include "byte_string.h"

class ConfigSettingKV;
/**
 * @brief The ConfigSetting class
 * 基于段+键值对的基础配置文件操作,遍历方式
 * for (ConfigSetting::Section &sect : set)
 * {
 *    for (ConfigSetting::KV &kv : sect)
 *    {
 *        GEN_Printf(LOG_DEBUG, "%s = %s", kv.key.string(), kv.val.string());
 *    }
 * }
 */
class ConfigSetting
{
public:
    struct KV {
        ByteString key, val;
    };

    class Section
    {
    public:        
        class Iterator
        {
        public:
            typedef KV T;
            typedef T  value_type;
            typedef T* pointer;
            typedef T& reference;

            Iterator(Section *arr, int i, int max)
                : array(arr)
                , kv{arr->keys[0], arr->values[0]}
                , index(i), max(max)
            {}
            Iterator(const Iterator &other) = default;
            Iterator(Iterator &&other) noexcept = default;
            ~Iterator() = default;

            Iterator &operator=(const Iterator &other)
            {
                if (&other != this)
                {
                    *this = other;
                }
                return *this;
            }
            Iterator& operator=(Iterator&& other) noexcept = default;

            Iterator& operator++()
            {
                index++;
                kv.key = array->keys[index];
                kv.val = array->values[index];
                return *this;
            }
            Iterator operator++(int)
            {
                Iterator __tmp = *this;
                ++(*this);
                return __tmp;
            }
            reference operator*()
            {
                return kv;
            }

            pointer operator->()
            {
                return &kv;
            }

            //Iterator& operator--() { return *this; }
            //Iterator operator--(int) { Iterator __tmp = *this; return __tmp; }

            bool operator==(const Iterator& oth) const
            {
                return index == oth.index;
            }

            bool operator!=(const Iterator& oth) const
            {
                return index != oth.index;
            }

            operator bool() const
            {
                return index < max;
            }

            ByteString key() { return array->keys[index]; }
            ByteString value() { return array->values[index]; }

            Section  *array;
            KV        kv;
            int index;
            int max;
        };

        Iterator begin()
        {
            return Iterator(this, 0, key_nr);
        }

        Iterator end()
        {
            return Iterator(this, key_nr, key_nr);
        }
        int size() const { return key_nr;}

        Section() {}

        /**
         * @brief getValue
         * @param key [in] key值
         * @return 返回相对应的值
         */
        ByteString getValue(const ByteString &key);
        void getSwapValue(const ByteString &key, ByteString &value);

        /**
         * @brief setValue
         *  新增一个键值对，需要做重复比较，保证了key的唯一性，新值会替换旧值
         * @param key [in] key值
         * @param val [in] value值
         * @return 返回新设置值 指针
         */
        ByteString setValue(const ByteString &key, const ByteString &val);

        //! 作重复比较，返回state = false表示这个val 没有变化
        ByteString setValueJudge(const ByteString &key, const ByteString &val, int &state);

        //! 新增一个键值对，不做重复比较，不保证key的唯一性
        ByteString newKeyValue(const ByteString &key, const ByteString &value);

        //! 移除段中包含的key
        void removeKey(const ByteString &key);

        //! 清除键值对，但是不清除内存
        void clear();

        //! 清除键值对，清除内存
        void distclean();

        /** Allocated number of keys */
        int key_nr_alloc;
        /** Key number in the section */
        int key_nr;
        /** Name of the section */
        ByteString  name;
        /** Array of keys */
        ByteString* keys;
        /** Array of values */
        ByteString* values;
    };

    class Iterator
    {
    public:
        typedef Section T;
        typedef T  value_type;
        typedef T* pointer;
        typedef T& reference;

        Iterator(T *arr, int i, int max)
            : array(arr), index(i), max(max)
        {}
        Iterator(const Iterator &other)
            : array(other.array)
            , index(other.index)
            , max(other.max)
        {}
        Iterator(Iterator &&other) noexcept = default;
        ~Iterator() = default;

        Iterator &operator=(const Iterator &other)
        {
            if (&other != this)
            {
                array = other.array;
                index = other.index;
                max = other.max;
            }
            return *this;
        }
        Iterator& operator=(Iterator&& other) noexcept = default;

        Iterator& operator++()
        {
            index++;
            return *this;
        }
        Iterator operator++(int)
        {
            Iterator __tmp = *this;
            ++(*this);
            return __tmp;
        }
        reference operator*()
        {
            return array[index];
        }

        pointer operator->()
        {
            return &array[index];
        }

        //Iterator& operator--() { return *this; }
        //Iterator operator--(int) { Iterator __tmp = *this; return __tmp; }

        bool operator==(const Iterator& oth) const
        {
            return index == oth.index;
        }

        bool operator!=(const Iterator& oth) const
        {
            return index != oth.index;
        }

        operator bool() const
        {
            return index < max;
        }

        T  *array;
        int index;
        int max;
    };

    Iterator begin()
    {
        return Iterator(sections, 0, section_nr);
    }

    Iterator end()
    {
        return Iterator(sections, section_nr, section_nr);
    }
    int size() const { return section_nr;}

    ConfigSetting();
    ~ConfigSetting();

    //! 加载配置文件
    bool loadFile(const char *file);
    //! 保存配置文件，首先保存在临时文件中，然后把名字修改
    bool saveFile(const char *file);
    //! 把当前配置的信息都保存在指定的文件中
    bool saveTmpFile(const char *file);

    //! 清除键值对，但是不清除内存
    void clear();

    /**
     * @brief getValue
     * @param sec [in] 段名字
     * @param key [in] key值
     * @return 返回相对应的值
     */
    ByteString getValue(const ByteString &sec, const ByteString &key);

    /**
     * @brief setValue
     * @param sec [in] 段名字
     * @param key [in] key值
     * @param val [in] value值
     * @return 返回新设置值 指针
     */
    ByteString setValue(const ByteString &sec, const ByteString &key, const ByteString &val);

    /**
     * @brief getSection
     * @param sec [in] 段名字
     * @return 获取当前整个段
     */
    Section*   getSection(const ByteString &sec);

    /**
     * @brief addSection
     * @param sec [in] 段名字
     * @param isOnly[in] 是否唯一段，
     *  true表示唯一，需要查找整个段，如果有名字就直接返回否者创建
     *  false 表示可以创建重名的数据段
     * @return 当前整个空段
     * @warning not used 没有实现这个功能
     */
    Section*   addSection(const ByteString &sec, bool isOnly);

    //! 移除段
    void removeSection(const ByteString &sec);
    //! 移除段中包含的key
    void removeKey(const ByteString &sec, const ByteString &key);

    //! 打印配置的全部信息
    void profile();

private:
    /** 分配节数 */
    int sect_nr_alloc;
    /** Number of sections */
    int section_nr;
    /** Pointer to section arrays */
    Section *sections;

    int      readSection(void* fp, Section* psect);
    Section *newCreateSection(const ByteString &sec);

    static char* get_section_name (char *section_line);

    static int get_key_value (char *key_line, char **mykey, char **myvalue);

    friend class ConfigSettingKV;
    friend class Section;
};

/**
 * @brief The ConfigSettingKV class
 * 基于键值对的基础配置文件操作, 遍历方式
 * for (ConfigSettingKV::KV &kv : config)
 * {
 *    GEN_Printf(LOG_DEBUG, "%s = %s", kv.key.string(), kv.val.string());
 * }
 */
class ConfigSettingKV
{
public:
    typedef ConfigSetting::KV KV;
    typedef ConfigSetting::Section::Iterator Iterator;
    Iterator begin() { return m_section.begin(); }
    Iterator end() { return m_section.end(); }
    int size() const { return m_section.size(); }

    ConfigSettingKV();
    ~ConfigSettingKV();

    //! 加载配置文件
    bool loadFile(const char *file);
    //! 保存配置文件，首先保存在临时文件中，然后把名字修改
    bool saveFile(const char *file);
    //! 把当前配置的信息都保存在指定的文件中
    bool saveTmpFile(const char *file);

    ByteString getValue( const ByteString &key)
    {
        return m_section.getValue(key);
    }
    void getSwapValue( const ByteString &key, ByteString &value)
    {
        m_section.getSwapValue(key, value);
    }

    ByteString setValue(const ByteString &key, const ByteString &val)
    {
        return m_section.setValue(key, val);
    }
    ByteString setValueJudge(const ByteString &key, const ByteString &val, int &state)
    {
        return m_section.setValueJudge(key, val, state);
    }

    void clear()
    {
        m_section.clear();
    }
    void removeKey( const ByteString &key)
    {
        m_section.removeKey(key);
    }

private:
    ConfigSetting::Section m_section;
};


#endif // _CONFIG_SETTING_H_
